// MSIDump.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

LPCWSTR arrTables[] = 
{
	L"ActionText",
	L"AdminExecuteSequence",
	L"AdminUISequence",
	L"AdvtExecuteSequence",
	L"AdvtUISequence",
	L"AppId",
	L"AppSearch",
	L"BBControl",
	L"Billboard",
	L"Binary",
	L"BindImage",
	L"CCPSearch",
	L"CheckBox",
	L"Class",
	L"ComboBox",
	L"CompLocator",
	L"Complus",
	L"Component",
	L"Condition",
	L"Control",
	L"ControlCondition",
	L"ControlEvent",
	L"CreateFolder",
	L"CustomAction",
	L"Dialog",
	L"Directory",
	L"DrLocator",
	L"DuplicateFile",
	L"Environment",
	L"Error",
	L"EventMapping",
	L"Extension",
	L"Feature",
	L"FeatureComponents",
	L"File",
	L"FileSFPCatalog",
	L"Font",
	L"Icon",
	L"IniFile",
	L"IniLocator",
	L"InstallExecuteSequence",
	L"InstallUISequence",
	L"IsolatedComponent",
	L"LaunchCondition",
	L"ListBox",
	L"ListView",
	L"LockPermissions",
	L"Media",
	L"MIME",
	L"MoveFile",
	L"MsiAssembly",
	L"MsiAssemblyName",
	L"MsiDigitalCertificate",
	L"MsiDigitalSignature",
	L"MsiEmbeddedChainer",
	L"MsiEmbeddedUI",
	L"MsiFileHash",
	L"MsiLockPermissionsEx",
	L"MsiPackageCertificate",
	L"MsiPatchCertificate",
	L"MsiPatchHeaders",
	L"MsiPatchMetadata",
	L"MsiPatchOldAssemblyFile",
	L"MsiPatchOldAssemblyName",
	L"MsiPatchSequence",
	L"MsiServiceConfig",
	L"MsiServiceConfigFailureActions",
	L"MsiSFCBypass",
	L"MsiShortcutProperty",
	L"ODBCAttribute",
	L"ODBCDataSource",
	L"ODBCDriver",
	L"ODBCSourceAttribute",
	L"ODBCTranslator",
	L"Patch",
	L"PatchPackage",
	L"ProgId",
	L"Property",
	L"PublishComponent",
	L"RadioButton",
	L"Registry",
	L"RegLocator",
	L"RemoveFile",
	L"RemoveIniFile",
	L"RemoveRegistry",
	L"ReserveCost",
	L"SelfReg",
	L"ServiceControl",
	L"ServiceInstall",
	L"SFPCatalog",
	L"Shortcut",
	L"Signature",
	L"TextStyle",
	L"TypeLib",
	L"UIText",
	L"Upgrade",
	L"Verb",
	L"_Columns",
	L"_Storages",
	L"_Streams",
	L"_Tables",
	L"_TransformView",
	L"_Validation"
};

BOOL DumpMSITable(MSIHANDLE hDb,LPCWSTR szTable);

int _tmain(int argc, _TCHAR* argv[])
{
	if (argc != 2)
	{
		wprintf(L"Usage : MSIDump.exe MSIPACKAGE_FILE_NAME.\r\n");
		return 0;
	}

	if (!::PathFileExists(argv[1]))
	{
		wprintf(L"%s dose not exist!\r\n");
		return 0;
	}

	MSIHANDLE hDb = 0;
	UINT nRet = 0;
	nRet = MsiOpenDatabase(argv[1],MSIDBOPEN_READONLY,&hDb);

	if (nRet != ERROR_SUCCESS)
	{
		wprintf(L"Invalid MSI Database.\r\n");
		return 0;
	}


	int tablecount = sizeof(arrTables) / sizeof(arrTables[0]);

	for (int i =0; i < tablecount; i++)
	{
		DumpMSITable(hDb,arrTables[i]);
	}
	
	getchar();
	return 0;
}

BOOL DumpMSITable(MSIHANDLE hDb,LPCWSTR szTable)
{
	WCHAR szBuffer[1024] = {0};
	DWORD dwBufferLen = 1024;

	UINT nRet = 0;
	MSIHANDLE hView = 0,hRecord = 0;
	wsprintf(szBuffer,L"SELECT * FROM %s",szTable);

	nRet = MsiDatabaseOpenView(hDb,szBuffer,&hView);

	if (nRet != ERROR_SUCCESS)
	{
		wprintf(L"Open View %s Faild.\r\n",szTable);
		return FALSE;
	}

	wprintf(L"**************************************** %s ****************************************\r\n",szTable);
	MsiViewExecute(hView,hRecord);

	while(ERROR_SUCCESS == MsiViewFetch(hView,&hRecord))
	{
		int fieldcount = MsiRecordGetFieldCount(hRecord);

		for (int i=0;i<=fieldcount;i++)
		{
			dwBufferLen = 1024;
			nRet = MsiRecordGetString(hRecord,i,szBuffer,&dwBufferLen);

			if (i > 0)
				wprintf(L" : ");

			wprintf(szBuffer);
		}

		wprintf(L"\r\n");
	}

	wprintf(L"\r\n");

	return TRUE;
}
